package com.atguigu.dga.governance.assessor.security;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.dga.governance.assessor.Assessor;
import com.atguigu.dga.governance.bean.AssessParam;
import com.atguigu.dga.governance.bean.GovernanceAssessDetail;
import com.atguigu.dga.governance.bean.GovernanceMetric;
import com.atguigu.dga.meta.bean.TableMetaInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.fs.permission.FsPermission;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

@Component("BEYOND_PERMISSION")
public class BeyondPermisssionAssessor extends Assessor {

    Map map=new HashMap();

    AtomicInteger  i=new AtomicInteger(0);

    // 准备阶段  1  访问工具   FileSystem
    //         2   访问的起点   一级目录集合
    //         3   存放结果的容器  List<String>   超过权限的文件或目录的路径清单
    //         4   计算过程中的参考值
    @Override
    public void checkProblem(AssessParam assessParam, GovernanceAssessDetail governanceAssessDetail)  {
         i.addAndGet(1);
        //1  访问工具   FileSystem
        TableMetaInfo tableMetaInfo = assessParam.getTableMetaInfo();
        String tableFsPath = tableMetaInfo.getTableFsPath();
        String tableFsOwner = tableMetaInfo.getTableFsOwner();
        FileSystem fileSystem=null;
        try {
              fileSystem = FileSystem.get(new URI(tableFsPath), new Configuration(), tableFsOwner);
        } catch ( Exception e) {
            throw new RuntimeException(e);
        }
        //   2   访问的起点   一级目录集合
        FileStatus[] fileStatuses;
        try {
            fileStatuses = fileSystem.listStatus(new Path(tableFsPath));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //         3   存放结果的容器  List<String>   超过权限的文件或目录的路径清单
        List<String >  beyondPathList = new ArrayList<>();
        //         4   计算过程中的参考值
        GovernanceMetric governanceMetric = assessParam.getGovernanceMetric();
        String metricParamsJson = governanceMetric.getMetricParamsJson();
        JSONObject paramJsonobj = JSON.parseObject(metricParamsJson);
        String filePermission = paramJsonobj.getString("file_permission");
        String dirPermission = paramJsonobj.getString("dir_permission");

        checkPermissionRec(fileSystem,fileStatuses,beyondPathList,filePermission,dirPermission);

        if(beyondPathList.size()>0){
            governanceAssessDetail.setAssessScore(BigDecimal.ZERO);
            governanceAssessDetail.setAssessProblem("超过参考权限："+ StringUtils.join(beyondPathList,",")  );
        }



    }



    //执行阶段
    //       遍历起点的所有一级目录
    //       1    叶子节点 (文件)
    //            处理 ： 判断是否超过权限
    //            如果超过权限 把路径写入到 结果容器中
    //       2    分支节点(目录)
    //            处理： 判断是否超过权限
    //             如果超过权限 把路径写入到 结果容器中
    //             再次展开子节点
    //             把子节点作为新的递归起点 再次进入本方法
    private void checkPermissionRec(FileSystem fileSystem, FileStatus[] fileStatuses, List<String> beyondPathList, String filePermission, String dirPermission) {
        for (FileStatus fileStatus : fileStatuses) {
            if (fileStatus.isFile()){
                boolean isBeyond=  checkPermissionFileStatus(fileStatus,filePermission);
                if(isBeyond){
                    beyondPathList.add(fileStatus.getPath().toString());
                }
            }else{
                boolean isBeyond=  checkPermissionFileStatus(fileStatus,dirPermission);
                if (isBeyond){
                    beyondPathList.add(fileStatus.getPath().toString());
                }
                FileStatus[] subFilStatus=null;
                try {
                      subFilStatus = fileSystem.listStatus(fileStatus.getPath());//再次展开子节点
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                //             把子节点作为新的递归起点 再次进入本方法
                checkPermissionRec(fileSystem,subFilStatus,beyondPathList,filePermission,dirPermission);

            }




        }
    }

    private boolean checkPermissionFileStatus(FileStatus fileStatus, String filePermission) {
        FsPermission permission = fileStatus.getPermission();
        int userOrdinal = permission.getUserAction().ordinal();
        int groupOrdinal = permission.getGroupAction().ordinal();
        int otherOrdinal = permission.getOtherAction().ordinal();
        int paramUserOrdinal = Integer.valueOf(filePermission.substring(0, 1));
        int paramGroupOrdinal = Integer.valueOf(filePermission.substring(1, 2));
        int paramOtherOrdinal = Integer.valueOf(filePermission.substring(2));
        if (userOrdinal > paramUserOrdinal || groupOrdinal > paramGroupOrdinal || otherOrdinal > paramOtherOrdinal) {
            return true;
        }
        return false;
    }
}
